
#include "IGlobal.h"
#include "ILibStdlib.h"
#include "ILibStdio.h"
#include "ILibMath.h"
#include "ILibBase.h"

#include "IClassBool.h"
#include "IClassByte.h"
#include "IClassChar.h"
#include "IClassShort.h"
#include "IClassInt.h"
#include "IClassLong.h"
#include "IClassReal.h"
#include "IClassFloat.h"
#include "IClassDouble.h"
#include "IClassString.h"
#include "IClassArray.h"
#include "IClassList.h"
#include "IClassSet.h"
#include "IClassMap.h"

#include "member_BScript.h"
#include "member_BSource.h"

using namespace BWE;

BMap<BString, BClassHolder>		member_BScript::basicClassMap;

member_BScript::member_BScript(BScript* script)
{
	boss = script;
	error = false;
	breaked = false;
	unlinked = false;
	running = false;
	debugging = false;
	global = 0;
	current = -1;

	if (basicClassMap.empty())
	{
		static BClassHolder boolClass = new ClassBool();
		static BClassHolder byteClass = new ClassByte();
		static BClassHolder charClass = new ClassChar();
		static BClassHolder shortClass = new ClassShort();
		static BClassHolder intClass = new ClassInt();
		static BClassHolder longClass = new ClassLong();
		static BClassHolder realClass = new ClassReal();
		static BClassHolder floatClass = new ClassFloat();
		static BClassHolder doubleClass = new ClassDouble();
		static BClassHolder stringClass = new ClassString();
		static BClassHolder arrayClass = new ClassArray();
		static BClassHolder listClass = new ClassList();
		static BClassHolder setClass = new ClassSet();
		static BClassHolder mapClass = new ClassMap();
		//static BClassHolder tableClass = new ClassTable();
		//static BClassHolder treeClass = new ClassTree();

		basicClassMap["bool"] = boolClass;
		basicClassMap["byte"] = byteClass;
		basicClassMap["char"] = charClass;
		basicClassMap["short"] = shortClass;
		basicClassMap["int"] = intClass;
		basicClassMap["long"] = longClass;
		basicClassMap["real"] = realClass;
		basicClassMap["float"] = floatClass;
		basicClassMap["double"] = doubleClass;
		basicClassMap["string"] = stringClass;
		basicClassMap["array"] = arrayClass;
		basicClassMap["list"] = listClass;
		basicClassMap["set"] = setClass;
		basicClassMap["map"] = mapClass;
	}

#ifdef linux
	if (0 != pthread_cond_init(&thread_cond, 0))
	{
		return;
	}
	pthread_mutexattr_t attr;
	pthread_mutexattr_init(&attr);
	pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
	if (0 != pthread_mutex_init(&thread_mutex, &attr))
	{
		return;
	}
#endif
	paused_thread_id = 0;
#ifdef _WIN32
	paused_handle = 0;
#endif
}
member_BScript::~member_BScript()
{

}

ILibrary* member_BScript::importLibrary(const BString& libname)
{
	if (libname == "cstdio" || libname == "stdio.h")
	{
		return ILibStdio::Instance();
	}
	if (libname == "cstdlib" || libname == "stdlib.h")
	{
		return ILibStdlib::Instance();
	}
	if (libname == "cmath" || libname == "math.h")
	{
		return ILibMath::Instance();
	}
	if (libname == "cbase" || libname == "base.h")
	{
		return ILibBase::Instance();
	}
	return 0;
}
const BString& member_BScript::cacheFile(const BString& fileName)
{
	BString fullName;
	for (int i = 0; i < includePaths.size(); i++)
	{
		const BString& path = includePaths[i];
		fullName.reset();
		fullName << '/' << path;
		const BString& text = cachedFileMap[fullName];
		if (text.size())
			return text;
	}
	return cachedFileMap.def();
}
bool member_BScript::createValue(BString& word, BValue& value)
{
	if (word[0] == '\"')
	{
		word.remove(0);
		if (!word.endWith('\"'))
		{
			errorMessage() << "string is not finished.";
			boss->emit(Signal_Error, message);
			return false;
		}
		word -= '\"';
		word.replace("\\n", '\n');
		word.replace("\\t", '\t');
		word.replace("\\r", '\r');
		value = word;
		return true;
	}
	if (word[0] == '\'')
	{
		word.remove(0);
		if (word.endWith('\''))
		{
			errorMessage() << "string is not finished.";
			boss->emit(Signal_Error, message);
			return false;
		}
		word -= '\'';
		word.replace("\\n", '\n');
		word.replace("\\t", '\t');
		word.replace("\\r", '\r');
		if (word.size() > 1)
		{

		}
		value = word[0];
		return true;
	}
	if (word == "true")
	{
		value = true;
		return true;
	}
	if (word == "false")
	{
		value = false;
		return true;
	}
	if (word.isNumber())
	{
		if (word.contain('.'))
		{
			if (word.endWith('f'))
			{
				float v = word.toFloat();
				value = v;
			}
			else
			{
				double v = word.toDouble();
				value = v;
			}
		}
		else
		{
			if (word.endWith("ul"))
			{
				unsigned long long v = word.toLong();
				value = v;
			}
			else if (word.endWith('l'))
			{
				long long v = word.toLong();
				value = v;
			}
			else
			{
				int v = word.toInt();
				value = v;
			}
		}
		return true;
	}
	for (int i = 0; i < enumMap.size(); i++)
	{
		auto it = enumMap.seek(i);
		const BString& type = it.key();
		if (it.value().empty())
			continue;
		BEnum* enm = *it;
		if (enm->contain(word))
		{
			value = enm->value(word);
			return true;
		}
	}
	return false;
}

BExp* member_BScript::cloneExp(BExp* exp) const
{
	BExp* newExp = new BExp();
	newExp->syntax = exp->syntax;
	newExp->type = exp->type;
	newExp->name = exp->name;
	newExp->value = exp->value;
	newExp->info = exp->info;
	newExp->subs = exp->subs;
	for (int i = 0; i < newExp->subs.size(); i++)
	{
		newExp->subs[i] = cloneExp(newExp->subs[i]);
	}
	newExp->params = exp->params;
	for (int i = 0; i < newExp->params.size(); i++)
	{
		newExp->params[i] = cloneExp(newExp->params[i]);
	}
	return newExp;
}
BString& member_BScript::errorMessage(int index)
{
	error = true;
	BString& text = message.fill<BString>();
	text.reset();
	text << index << " : ";
	text << "error : ";
	return text;
}
BString& member_BScript::errorMessage(BExp* exp)
{
	error = true;
	BString& text = message.fill<BString>();
	text.reset();
	if (exp)
	{
		if (exp->info.size())
			text << exp->info << " : ";
		else
			text << current << " : ";
	}
	text << "error : ";
	return text;
}
void member_BScript::sourceMessage(const BValue& value)
{
	error = true;
	BString& text = message.fill<BString>();
	text << (const BString&)value << '\n';
	boss->emit(Signal_Message, value);
}

void member_BScript::combine()
{
	inclibs.clear();
	declMap.clear();
	enumMap.clear();
	classMap.clear();
	functionMap.clear();
	BExpArray externExps;
	for (int i = 0; i < sources.size(); i++)
	{
		const BSource* source = sources[i];
		for (int i = 0; i < source_member(source)->includes.size(); i++)
		{
			BExp* exp = source_member(source)->includes[i];
			for (int i = 0; i < inclibs.size(); i++)
			{
				BExp* inc = inclibs[i];
				if (inc->name == exp->name)
				{
					exp = 0;
					break;
				}
			}
			if (exp)
			{
				inclibs.append(exp);
			}
		}
		for (int i = 0; i < source_member(source)->declares.size(); i++)
		{
			BExp* exp = source_member(source)->declares[i];
			if (exp->value == Syntax_Extern)
			{
				externExps.append(exp);
				continue;
			}
			if (BExp* decl = declMap(exp->name))
			{
				errorMessage(exp) << "Link : variant " << exp->name << " is redefined.";
				boss->emit(Signal_Message, message);
				errorMessage(decl) << decl->type << ' ' << decl->name << " has been defined.";
				boss->emit(Signal_Message, message);
				continue;
			}
			declMap[exp->name] = exp;
		}
		for (auto fit = source_member(source)->functionMap.begin(); fit.valid(); fit++)
		{
			const BString& funcName = fit.key();
			FuncInfo* finfo = fit.value();
			if (finfo->sfunc->subs.empty())
				continue;
			if (this->functionMap.contain(funcName))
			{
				errorMessage(finfo->sfunc) << "Link : function " << funcName << " is redefined.";
				boss->emit(Signal_Message, message);
				continue;
			}
			this->functionMap.insert(funcName, *fit);
		}
		for (auto cit = source_member(source)->enumMap.begin(); cit.valid(); cit++)
		{
			const BString& type = cit.key();
			if (presetEnumMap.contain(type))
			{
				errorMessage() << "enum " << type << " has been defined in presets.";
				boss->emit(Signal_Message, message);
				continue;
			}
			BEnum* enm = cit.value();
			if (enm->empty())
				continue;
			if (BEnum* enm1 = this->enumMap[type])
			{
				BExp* exp = enm->asset();
				BExp* exp1 = enm1->asset();
				if (exp && exp->info.size() && exp->info != exp1->info)
				{
					errorMessage() << "enum " << type << " is redefined.";
					boss->emit(Signal_Message, message);
				}
				continue;
			}
			else
			{
				this->enumMap[type] = cit.value();
			}
		}
		for (auto cit = source_member(source)->classMap.begin(); cit.valid(); cit++)
		{
			const BString& type = cit.key();
			if (presetClassMap.contain(type))
			{
				errorMessage() << "class " << type << " has been defined in presets.";
				boss->emit(Signal_Message, message);
				continue;
			}
			if (BClass* cls = classMap[type])
			{
				BMap<BString, MethodInfoHolder>& methodMap = class_member(cls)->methodMap;
				BClass* src_cls = cit.value();
				for (auto it = class_member(src_cls)->methodMap.begin(); it.valid(); ++it)
				{
					const BString& name = it.key();
					MethodInfo* src_method = *it;
					if (src_method->method.empty())
						continue;
					if (src_method->method == 0)
						continue;
					BExp* sfunc0 = src_method->method;
					if (sfunc0 == 0)
						continue;
					BExp* sfunc1 = methodMap(name)->method;
					if (sfunc1 && sfunc1->info == sfunc0->info)
						continue;
					methodMap[name]->method = sfunc0;
				}
			}
			else
			{
				classMap[type] = cit.value();
			}
		}
	}
	for (int i = 0; i < externExps.size(); i++)
	{
		BExp* exp = externExps[i];
		BExp* decl = declMap(exp->name);
		if (!decl)
		{
			errorMessage(exp) << "Link : extern " << exp->name << " is unfound.";
			boss->emit(Signal_Message, message);
			continue;
		}
		if (decl->type != exp->type)
		{
			errorMessage(exp) << "Link : extern variant " << exp->name << " has different type.";
			boss->emit(Signal_Message, message);
			errorMessage(decl) << decl->type << ' ' << decl->name << " has been defined.";
			boss->emit(Signal_Message, message);
		}
	}
	for (auto cit = classMap.begin(); cit.valid(); cit++)
	{
		BClass* cls = cit.value();
		BExpHolderArray& declares = class_member(cls)->declares;
		if (declares.empty())
			continue;
		for (int i = 0; i < declares.size(); i++)
		{
			declares[i]->syntax = Syntax_Self;
		}
		for (int i = 0; i < class_member(cls)->methodMap.size(); i++)
		{
			auto mit = class_member(cls)->methodMap.seek(i);
			if (mit.key().beginWith(cit.key()))
			{
				MethodInfo* minfo = mit.value();
				BExp* method = minfo->method;
				if (!method)
					continue;
				int begin = 0;
				for (int s = 0; s < method->subs.size(); s++)
				{
					if (method->subs[s]->syntax == Syntax_Begin)
					{
						begin = s;
						break;
					}
				}
				method->subs.insert(begin, declares);
			}
		}
		declares.clear();
	}
}
void member_BScript::serialize()
{
	sequence.clear();
	for (int i = 0; i < inclibs.size(); i++)
	{
		BExp* inc = inclibs[i];
		serialize(inc);
	}
	for (auto it = this->enumMap.begin(); it.valid(); ++it)
	{
		BEnum* enm = *it;
		if (BExp* exp = enm->asset())
		{
			serialize(exp);
		}
	}
	for (auto it = this->declMap.begin(); it.valid(); ++it)
	{
		BExp* decl = *it;
		serialize(decl);
	}
	BExp* jump = new BExp(Syntax_Jump);
	sequence.append(jump);
	for (auto fit = this->functionMap.begin(); fit.valid(); ++fit)
	{
		FuncInfo* finfo = *fit;
		if (finfo->sfunc)
		{
			finfo->line = sequence.size();
			serialize(finfo->sfunc);
		}
	}
	for (auto it = this->classMap.begin(); it.valid(); ++it)
	{
		BClass* cls = it.value();
		BExp* exp = new BExp(Syntax_Class);
		exp->name = it.key();
		for (int i = 0; i < class_member(cls)->inherits.size(); i++)
		{
			BExp* inherit = class_member(cls)->inherits[i];
			inherit->info.clear();
			inherit->value.clear();
			inherit->subs.clear();
			inherit->params.clear();
			inherit->value = boss->findClass(inherit->type);
			exp->params.append(inherit);
		}
		for (int i = 0; i < class_member(cls)->variants.size(); i++)
		{
			VariantInfo& vinfo = class_member(cls)->variants[i];
			BExp* decl = new BExp(Syntax_Decl);
			decl->type = vinfo.type;
			decl->name = vinfo.name;
			decl->value = vinfo.access;
			exp->params.append(decl);
		}
		sequence.append(exp);
		for (auto mit = class_member(cls)->methodMap.begin(); mit.valid(); ++mit)
		{
			const BString& name = mit.key();
			MethodInfo* minfo = mit.value();
			if (BExp* sfunc = minfo->method)
			{
				minfo->line = sequence.size();
				serialize(sfunc);
			}
			if (minfo->virt)
			{
				BExp* vfunc = new BExp(Syntax_Method);
				vfunc->type = minfo->type;
				vfunc->name = mit.key();
				vfunc->value = minfo->method;
				exp->params.append(vfunc);
			}
		}
	}
	jump->type = "int";
	jump->value = sequence.size();
}
void member_BScript::serialize(BExp* exp)
{
	switch (exp->syntax)
	{
	case Syntax_None:
	{
		for (int i = 0; i < exp->subs.size(); i++)
		{
			serialize(exp->subs[i]);
		}
		break;
	}
	case Syntax_Include:
	{
		exp->info.clear();
		exp->subs.clear();
		exp->params.clear();
		sequence.append(exp);
		break;
	}
	case Syntax_Assign:
	{
		for (int i = 0; i < exp->subs.size(); i++)
		{
			serialize(exp->subs[i]);
		}
		for (int i = 0; i < exp->params.size(); i++)
		{
			serialize(exp->params[i]);
		}
		exp->subs.clear();
		exp->params.clear();
		sequence.append(exp);
		break;
	}
	case Syntax_Cast:
	{
		for (int i = 0; i < exp->subs.size(); i++)
		{
			serialize(exp->subs[i]);
		}
		for (int i = 0; i < exp->params.size(); i++)
		{
			serialize(exp->params[i]);
		}
		exp->subs.clear();
		exp->params.clear();
		sequence.append(exp);
		break;
	}
	case Syntax_Value:
	{
		sequence.append(exp);
		break;
	}
	case Syntax_Name:
	{
		if (exp->subs.size())
		{
			for (int i = 0; i < exp->subs.size(); i++)
				exp->name << exp->subs[i]->name << '.';
			exp->name -= '.';
			exp->subs.clear();
		}
		sequence.append(exp);
		break;
	}
	case Syntax_Self:
	{
		sequence.append(exp);
		for (int i = 0; i < exp->subs.size(); i++)
		{
			serialize(exp->subs[i]);
		}
		break;
	}
	case Syntax_Decl:
	{
		sequence.append(exp);
		for (int i = 0; i < exp->subs.size(); i++)
		{
			serialize(exp->subs[i]);
		}
		exp->subs.clear();
		exp->params.clear();
		break;
	}
	case Syntax_Array:
	{
		sequence.append(exp);
		for (int i = 0; i < exp->subs.size(); i++)
		{
			serialize(exp->subs[i]);
		}
		exp->subs.clear();
		exp->params.clear();
		break;
	}
	case Syntax_New:
	{
		sequence.append(exp);
		for (int i = 0; i < exp->subs.size(); i++)
		{
			serialize(exp->subs[i]);
		}
		exp->subs.clear();
		exp->params.clear();
		break;
	}
	case Syntax_Init:
	{
		for (int i = 0; i < exp->subs.size(); i++)
		{
			serialize(exp->subs[i]);
		}
		for (int i = 0; i < exp->params.size(); i++)
		{
			serialize(exp->params[i]);
		}
		exp->subs.clear();
		exp->params.clear();
		sequence.append(exp);
		break;
	}
	case Syntax_Call:
	{
		for (int i = 0; i < exp->subs.size(); i++)
		{
			serialize(exp->subs[i]);
		}
		if (FuncInfo* func = exp->value)
		{
			BExp* res = new BExp();
			res->syntax = Syntax_Value;
			res->type = exp->type;
			sequence.append(res);
		}
		for (int i = 0; i < exp->params.size(); i++)
		{
			serialize(exp->params[i]);
		}
		exp->subs.clear();
		exp->params.clear();
		sequence.append(exp);
		break;
	}
	case Syntax_Opera:
	case Syntax_And:
	case Syntax_Or:
	case Syntax_Equal:
	{
		for (int i = 0; i < exp->subs.size(); i++)
		{
			serialize(exp->subs[i]);
		}
		for (int i = 0; i < exp->params.size(); i++)
		{
			serialize(exp->params[i]);
		}
		exp->subs.clear();
		exp->params.clear();
		sequence.append(exp);
		break;
	}
	case Syntax_Test:
	{
		for (int i = 0; i < exp->params.size(); i++)
		{
			serialize(exp->params[i]);
		}
		for (int i = 0; i < exp->subs.size(); i++)
		{
			serialize(exp->subs[i]);
		}
		exp->subs.clear();
		exp->params.clear();
		sequence.append(exp);
		break;
	}
	case Syntax_Begin:
	{
		sequence.append(exp);
		break;
	}
	case Syntax_End:
	{
		sequence.append(exp);
		break;
	}
	case Syntax_Return:
	{
		for (int i = 0; i < exp->params.size(); i++)
		{
			BExp* param = exp->params[i];
			serialize(param);
		}
		exp->params.clear();
		sequence.append(exp);
		break;
	}
	case Syntax_Enum:
	{
		for (int i = 0; i < exp->subs.size(); i++)
		{
			BExp* sub = exp->subs[i];
			if (sub->syntax == Syntax_Value)
			{
				BExp* key = new BExp(Syntax_Key);
				key->name = sub->name;
				key->value = sub->value;
				exp->params.append(key);
				continue;
			}
		}
		exp->subs.clear();
		sequence.append(exp);
		break;
	}
	case Syntax_Key:
	{
		sequence.append(exp);
		break;
	}
	case Syntax_If:
	{
		sequence.append(new BExp(Syntax_Begin));
		serialize(exp->params.first());
		sequence.append(exp);
		for (int i = 0; i < exp->subs.size(); i++)
		{
			serialize(exp->subs[i]);
		}
		if (exp->params.size() > 1)
		{
			BExp* prev = exp;
			for (int i = 1; i < exp->params.size(); i++)
			{
				BExp* next = exp->params[i];
				sequence.append(next);
				prev->type = "int";
				prev->value = sequence.size();
				for (int s = 0; s < next->subs.size(); s++)
				{
					serialize(next->subs[s]);
				}
				next->subs.clear();
				prev = next;
			}
			prev->type = "int";
			prev->value = sequence.size();
		}
		else
		{
			exp->type = "int";
			exp->value = sequence.size();
		}
		sequence.append(new BExp(Syntax_End));
		exp->params.clear();
		exp->subs.clear();
		break;
	}
	case Syntax_While:
	{
		BExpArray& exps = loopStack.push();

		int loop = sequence.size();
		{
			sequence.append(new BExp(Syntax_Begin, loop));
			serialize(exp->params.first());
			sequence.append(exp);
			for (int i = 0; i < exp->subs.size(); i++)
			{
				serialize(exp->subs[i]);
			}
			serialize(new BExp(Syntax_Continue));
		}
		int exit = sequence.size();
		sequence.append(new BExp(Syntax_End, loop));

		for (int i = 0; i < exps.size(); i++)
		{
			BExp* low = exps.at(i);
			if (low->syntax == Syntax_Break)
			{
				low->type = "int";
				low->value = exit;
			}
			if (low->syntax == Syntax_Continue)
			{
				low->type = "int";
				low->value = loop + 1;
				continue;
			}
		}

		exp->type = "int";
		exp->value = exit;
		exp->params.clear();
		exp->subs.clear();

		loopStack.pop(1);
		break;
	}
	case Syntax_For:
	{
		BExpArray& exps = loopStack.push();

		int begin = sequence.size();
		sequence.append(new BExp(Syntax_Begin, begin));
		serialize(exp->params.first());

		int loop = sequence.size();
		sequence.append(new BExp(Syntax_Begin, loop));
		serialize(exp->params[1]);
		sequence.append(exp);

		for (int i = 0; i < exp->subs.size(); i++)
		{
			serialize(exp->subs[i]);
		}
		int end = sequence.size();
		sequence.append(new BExp(Syntax_End, loop));

		serialize(exp->params[2]);
		sequence.append(new BExp(Syntax_Jump, loop));
		int exit = sequence.size();
		sequence.append(new BExp(Syntax_End, begin));

		for (int i = 0; i < exps.size(); i++)
		{
			BExp* low = exps.at(i);
			if (low->syntax == Syntax_Break)
			{
				low->type = "int";
				low->value = exit;
				continue;
			}
			if (low->syntax == Syntax_Continue)
			{
				low->type = "int";
				low->value = end;
				continue;
			}
		}

		exp->type = "int";
		exp->value = exit;
		exp->params.clear();
		exp->subs.clear();

		loopStack.pop(1);
		break;
	}
	case Syntax_Break:
	case Syntax_Continue:
	{
		BExpArray& exps = loopStack.last();
		exps.append(exp);
		sequence.append(exp);
		break;
	}
	case Syntax_Function:
	{
		sequence.append(exp);
		for (int i = 0; i < exp->params.size(); i++)
		{
			exp->params[i]->info.clear();
		}
		for (int i = 0; i < exp->subs.size(); i++)
		{
			serialize(exp->subs[i]);
		}
		int retpos = sequence.size() - 1;
		for (int i = retpos - 1; i >= 0; i--)
		{
			BExp* sub = sequence[i];
			if (sub == exp)
				break;
			if (sub->syntax == Syntax_Return)
			{
				sub->type = "int";
				sub->value = retpos;
			}
		}
		exp->subs.clear();
		break;
	}
	case Syntax_Method:
	{
		sequence.append(exp);
		for (int i = 0; i < exp->subs.size(); i++)
		{
			serialize(exp->subs[i]);
		}
		int retpos = sequence.size() - 1;
		for (int i = retpos - 1; i >= 0; i--)
		{
			BExp* sub = sequence[i];
			if (sub == exp)
				break;
			if (sub->syntax == Syntax_Return)
			{
				sub->type = "int";
				sub->value = retpos;
			}
		}
		exp->subs.clear();
		break;
	}
	default:
		break;
	}
}
void member_BScript::link()
{
	BString type;
	BString name;
	for (int i = 0; i < sequence.size(); i++)
	{
		BExp* exp = sequence[i];
		if (exp->syntax == Syntax_Init)
		{
			if (exp->name.contain(':'))
			{
				int split = exp->name.find(':');
				exp->name.substr(type, 0, split);
				BClass* cls = boss->findClass(type);
				if (cls == 0)
				{
					errorMessage(i) << "Link : class " << type << " is undefined.";
					boss->emit(Signal_Message, message);
					continue;
				}
				exp->name.substr(name, split + 2);
				MethodInfo* minfo = class_member(cls)->methodMap(name);
				if (!minfo)
				{
					errorMessage(i) << "Link : method " << exp->name << " is lost.";
					boss->emit(Signal_Message, message);
					continue;
				}
				exp->value = minfo;
			}
			else
			{
				FuncInfo* finfo = findFunction(exp->name);
				if (finfo == 0)
				{
					errorMessage(i) << "Link : function " << exp->name << " is lost.";
					boss->emit(Signal_Message, message);
					continue;
				}
				exp->value = finfo;
			}
			continue;
		}
		if (exp->syntax == Syntax_Call)
		{
			if (exp->name.contain(':'))
			{
				int split = exp->name.find(':');
				exp->name.substr(type, 0, split);
				BClass* cls = boss->findClass(type);
				if (cls == 0)
				{
					errorMessage(i) << "Link : class " << type << " is undefined.";
					boss->emit(Signal_Message, message);
					continue;
				}
				exp->name.substr(name, split + 2);
				MethodInfo* minfo = class_member(cls)->methodMap(name);
				if (!minfo)
				{
					errorMessage(i) << "Link : method " << exp->name << " is lost.";
					boss->emit(Signal_Message, message);
					continue;
				}
				exp->value = minfo;
			}
			else
			{
				FuncInfo* finfo = findFunction(exp->name);
				if (finfo == 0)
				{
					errorMessage(i) << "Link : function " << exp->name << " is lost.";
					boss->emit(Signal_Message, message);
					continue;
				}
				exp->value = finfo;
			}
			continue;
		}
		if (exp->syntax == Syntax_Opera)
		{
			if (exp->name == '!')
			{
				continue;
			}
			int split = exp->name.find(':');
			exp->name.substr(type, 0, split);
			if (type.empty())
			{
				errorMessage(i) << "Link : operator " << exp->name << " is missed.";
				boss->emit(Signal_Message, message);
				continue;
			}
			BClass* cls = boss->findClass(type);
			if (cls == 0)
			{
				errorMessage(i) << "Link : class " << type << " is undefined.";
				boss->emit(Signal_Message, message);
				continue;
			}
			exp->name.substr(name, split + 2);
			MethodInfo* minfo = class_member(cls)->methodMap(name);
			if (!minfo)
			{
				errorMessage(i) << "Link : operator " << exp->name << " is lost.";
				boss->emit(Signal_Message, message);
				continue;
			}
			exp->value = minfo;
		}
		if (exp->syntax == Syntax_Class)
		{
			if (BClass* cls = exp->value)
			{
				if (BExp* inherit = class_member(cls)->inherits.first())
				{
					inherit->value = boss->findClass(inherit->type);
					if (inherit->value.empty())
					{
						errorMessage(i) << "class " << exp->name << " inherits failed from " << inherit->type;
						boss->emit(Signal_Message, message);
					}
				}
			}
		}
	}
}

void member_BScript::debug(BExp* exp)
{
	if (sequence.check(current))
	{
		if (error)
		{
			breaked = true;
			boss->post(Signal_Breaked, new BString(current));
		}
		else
		{
			const BString& info = sequence[current]->info;
			for (int i = 0; i < breakpointSet.size(); i++)
			{
				const BString& breakpoint = breakpointSet[i];
				if (breakpoint.contain(':'))
				{
					if (breakpoint == info)
					{
						breaked = true;
						boss->post(Signal_Breaked, breakpoint);
						break;
					}
					continue;
				}
				int number = breakpoint.toInt();
				if (number == current)
				{
					breaked = true;
					boss->post(Signal_Breaked, breakpoint);
					break;
				}
			}
		}
		if (!breaked && command.size())
		{
			if (command.contain(':'))
			{
				if (exp->info.size())
				{
					if (command == exp->info)
					{
						breaked = true;
						boss->post(Signal_Breaked, command);
						command.reset();
					}
				}
			}
			else if (command == "next")
			{
				if (current < sequence.size() - 1)
				{
					BExp* next = sequence.at(current + 1);
					if (next->info.size())
					{
						breaked = true;
						boss->post(Signal_Breaked, next->info);
						command.reset();
					}
				}
			}
			else if (command == "step")
			{
				breaked = true;
				command = current;
				boss->post(Signal_Breaked, command);
				command.reset();
			}
			else if (command.isNumber())
			{
				int number = command.toInt();
				if (number == current)
				{
					breaked = true;
					boss->post(Signal_Breaked, command);
					command.reset();
				}
			}
		}
#ifdef linux
		if (breaked)
		{
			pthread_t thread_id = pthread_self();
			if (app_thread_id == thread_id)
			{
				while (!app_done)
				{
					if (boss->trylock())
					{
						if (!breaked)
						{
							boss->unlock();
							break;
						}
						boss->unlock();
					}
					App_CycleBegin();
					App_Event();
					App_Signal();
					App_Update();
					App_Frame();
					App_CycleEnd();
				}
			}
			else
			{
				boss->unlock();
				paused_thread_id = thread_id;
				pthread_cond_wait(&thread_cond, &thread_mutex);
				paused_thread_id = 0;
			}
		}
#endif

#ifdef _WIN32
		DWORD thread_id = GetCurrentThreadId();
		if (breaked)
		{
			if (app_thread_id == thread_id)
			{
				while (!app_done)
				{
					if (boss->trylock())
					{
						if (!breaked)
						{
							boss->unlock();
							break;
						}
						boss->unlock();
					}
					App_CycleBegin();
					App_Event();
					App_Signal();
					App_Update();
					App_Frame();
					App_CycleEnd();
				}
			}
			else
			{
				boss->unlock();
				paused_thread_id = thread_id;
				paused_handle = OpenThread(THREAD_ALL_ACCESS, false, thread_id);
				DWORD ret = SuspendThread(paused_handle);
				CloseHandle(paused_handle);
				paused_thread_id = 0;
				paused_handle = 0;
			}
		}
#endif
	}
}
void member_BScript::debugResume()
{
#ifdef linux
	pthread_cond_signal(&thread_cond);
#else
	ResumeThread(paused_handle);
#endif
}
void member_BScript::routine()
{
#ifdef linux
	pthread_t thread_id = pthread_self();
	if (app_thread_id == thread_id)
#endif
#ifdef _WIN32
	DWORD thread_id = GetCurrentThreadId();
	if (app_thread_id == thread_id)
#endif
	{
		BReal workTime = BReal(1) / app_frequency;
		BReal timePass = bTime() - app_beginTime;
		if (timePass > workTime)
		{
			App_CycleBegin();
			App_Event();
			App_Signal();
			App_Update();
			App_Frame();
			App_CycleEnd(false);
		}
	}
}

int member_BScript::perform(BExp* exp)
{
	AutoLock lock(boss);
	switch (exp->syntax)
	{
	case Syntax_Include:
	{
		return current + 1;
	}
	case Syntax_Assign:
	{
		int size = stack.size();
		BValue& value0 = stack[size - 2];
		BValue& value1 = stack[size - 1];
		value0.refer() = value1.refer();
		this->backStack(size - 1);
		return current + 1;
	}
	case Syntax_Cast:
	{
		int size = stack.size();
		BValue& value0 = stack[size - 2];
		value0.clear();
		BValue& value1 = stack[size - 1];
		if (BClass* cls = value1)
		{
			ParamInfo pinfo = exp->type;
			if (cls->isTyped(pinfo.type))
				value0.refer() = value1.refer();
		}
		return current + 1;
	}
	case Syntax_Value:
	{
		typeMap[stack.size()] = exp->type;
		nameMap[stack.size()] = exp->name;
		BValue& value = stack.push();
		value = exp->value;
		return current + 1;
	}
	case Syntax_Name:
	{
		if (BValue* ptr = findVariant(exp->name))
		{
			BValue& value = stack.push();
			value = ptr;
			return current + 1;
		}
		errorMessage(exp) << "named variant lost : " << exp->name << '.';
		boss->post(Signal_Error, message);
		return current + 1;
	}
	case Syntax_Self:
	{
		CallInfo* cinfo = 0;
		for (int i = stack.size() - 1; i >= 0; i--)
		{
			cinfo = stack[i];
			if (cinfo)
				break;
		}
		if (cinfo)
		{
			if (!cinfo->self)//for meta class.
				break;
			BClass* self = cinfo->self;
			if (exp->name.empty())
			{
				BValue& var = stack.push();
				var = self;
				return current + 1;
			}
			BValue* ptr = class_member(self)->findValue(exp->name);
			BValue& var = stack.push(ptr);
			return current + 1;
		}
		errorMessage(exp) << "self named variant lost : " << exp->name << '.';
		boss->post(Signal_Error, message);
		return current;
	}
	case Syntax_New:
	{
		BValue& value = stack.push();
		if (BClass* cls = boss->findClass(exp->type))
		{
			if (!class_member(cls)->ismeta)
			{
				BClass* self = cls->clone();
				class_member(self)->script = boss;
				value = self;
			}
		}
		return current + 1;
	}
	case Syntax_Decl:
	{
		if (exp->type.endWith('&'))
		{
			typeMap[stack.size()] = exp->type;
			nameMap[stack.size()] = exp->name;
			BValue& value = stack.push();
			return current + 1;
		}
		if (exp->type.endWith('*'))
		{
			typeMap[stack.size()] = exp->type;
			nameMap[stack.size()] = exp->name;
			BValue& value = stack.push();
			return current + 1;
		}
		typeMap[stack.size()] = exp->type;
		nameMap[stack.size()] = exp->name;
		BValue& value = stack.push();
		if (BClass* cls = boss->findClass(exp->type))
		{
			if (!class_member(cls)->ismeta)
			{
				BClass* self = cls->clone();
				class_member(self)->script = boss;
				value = self;
			}
		}
		return current + 1;
	}
	case Syntax_Array:
	{
		if (exp->type.endWith('&'))
		{
			typeMap[stack.size()] = exp->type;
			nameMap[stack.size()] = exp->name;
			BValue& var = stack.push();
			return current + 1;
		}
		if (exp->type.endWith('*'))
		{
			typeMap[stack.size()] = exp->type;
			nameMap[stack.size()] = exp->name;
			BValue& var = stack.push();
			return current + 1;
		}
		typeMap[stack.size()] = exp->type;
		nameMap[stack.size()] = exp->name;
		BValue& value = stack.push();
		if (BClass* cls = boss->findClass(exp->type))
		{
			if (!class_member(cls)->ismeta)
			{
				BClass* self = cls->clone();
				class_member(self)->script = boss;
				value = self;
			}
		}
		if (ClassArray* acls = value)
		{
			BValueArray* array = new BValueArray();
			array->reserve(exp->value);
			acls->setAsset(array);
		}
		return current + 1;
	}
	case Syntax_Init:
	{
		if (MethodInfo* minfo = exp->value)
		{
			int top = stack.size() - minfo->params.size();
			BValue* argv = stack.data() + top - 1;
			if (BExp* sfunc = minfo->method)
			{
				for (int i = 0; i < minfo->params.size(); i++)
				{
					ParamInfo& param = minfo->params[i];
					if (argv[i].empty())
						argv[i] = param.value;
					nameMap[top + i] = param.name;
					typeMap[top + i] = param.type;
				}
				nameMap[stack.size()] = exp->name;
				typeMap[stack.size()] = "call";
				CallInfo* cinfo = new CallInfo();
				cinfo->type = minfo->type;
				cinfo->pos = current + 1;
				cinfo->top = top;
				cinfo->self = argv[0];
				stack.push(cinfo);
				return minfo->line;
			}
			if (BClass::Method method = minfo->method)
			{
				BClass* self = argv[0];
				int argc = minfo->params.size() + 1;
				(self->*method)(argc, argv);
				if (minfo->type.size())
				{
					top++;
				}
				this->backStack(top);
				return current + 1;
			}
		}
		errorMessage(exp) << "perform init method failed : " << exp->name << " is invalid.";
		boss->post(Signal_Error, message);
		return current;
	}
	case Syntax_Call:
	{
		if (FuncInfo* finfo = exp->value)
		{
			int argc = finfo->params.size() + 1;
			int top = stack.size() - argc;
			BValue* argv = stack.data() + top;
			argv[0] = BValue(boss, true);
			if (finfo->cfunc)
			{
				finfo->cfunc(argc, argv);
				if (finfo->type.size())
					top++;
				this->backStack(top);
				return current + 1;
			}
			for (int i = 0; i < finfo->params.size(); i++)
			{
				ParamInfo& param = finfo->params[i];
				if (argv[1 + i].empty())
					argv[1 + i] = param.value;
				nameMap[top + 1 + i] = param.name;
				typeMap[top + 1 + i] = param.type;
			}
			nameMap[stack.size()] = exp->name;
			typeMap[stack.size()] = "call";
			CallInfo* cinfo = new CallInfo();
			cinfo->type = finfo->type;
			cinfo->pos = current + 1;
			cinfo->top = top;
			stack.push(cinfo);
			return finfo->line;
		}
		if (MethodInfo* minfo = exp->value)
		{
			int argc = minfo->params.size() + 1;
			int top = stack.size() - argc;
			BValue* argv = stack.data(top);
			BClass* self = argv[0];
			if (minfo->virt)
			{
				if (!self)
				{
					errorMessage(exp) << "virtual call method failed : no self for " << exp->name;
					boss->post(Signal_Error, message);
					return current;
				}
				const BString& name = exp->name;
				minfo = class_member(self)->methodMap(name.cstr() + name.find(':') + 2);
				if (!minfo)
				{
					errorMessage(exp) << "virtual call " << exp->name << " is lost.";
					boss->post(Signal_Error, message);
					return current;
				}
			}
			if (!minfo->meta)
			{
				if (!self)
				{
					errorMessage(exp) << "self of method is null : " << exp->name << '.';
					boss->post(Signal_Error, message);
					return current;
				}
				if (!class_member(self)->script)
				{
					errorMessage(exp) << "script of class is null : " << exp->name << '.';
					boss->post(Signal_Error, message);
					return current;
				}
			}
			if (BExp* sfunc = minfo->method)
			{
				for (int i = 0; i < minfo->params.size(); i++)
				{
					ParamInfo& param = minfo->params[i];
					if (argv[1 + i].empty())
						argv[1 + i] = param.value;
					nameMap[top + 1 + i] = param.name;
					typeMap[top + 1 + i] = param.type;
				}
				nameMap[stack.size()] = exp->name;
				typeMap[stack.size()] = "call";
				CallInfo* cinfo = new CallInfo();
				cinfo->type = minfo->type;
				cinfo->pos = current + 1;
				cinfo->top = top;
				cinfo->self = self;
				stack.push(cinfo);
				return minfo->line;
			}
			if (BClass::Method method = minfo->method)
			{
				(self->*method)(argc, argv);
				if (minfo->type.size())
					top++;
				this->backStack(top);
				return current + 1;
			}
		}
		errorMessage(exp) << "perform call funtion failed : " << exp->name << " is invalid.";
		boss->post(Signal_Error, message);
		return current;
	}
	case Syntax_Opera:
	{
		if (MethodInfo* minfo = exp->value)
		{
			int argc = minfo->params.size() + 1;
			int top = stack.size() - argc;
			BValue* argv = stack.data() + top;
			if (BExp* sfunc = minfo->method)
			{
				nameMap[stack.size()] = exp->name;
				typeMap[stack.size()] = "call";
				CallInfo* cinfo = new CallInfo();
				cinfo->type = minfo->type;
				cinfo->pos = current + 1;
				cinfo->top = top;
				cinfo->self = argv[0];
				stack.push(cinfo);
				return minfo->line;
			}
			if (BClass::Method method = minfo->method)
			{
				BClass* self = argv[0];
				(self->*method)(argc, argv);
				if (minfo->type.size())
				{
					top++;
				}
				this->backStack(top);
				return current + 1;
			}
		}
		errorMessage(exp) << "perform call funtion failed : " << exp->name << " is invalid.";
		boss->post(Signal_Error, message);
		return current;
	}
	case Syntax_Test:
	{
		BValue& value = stack.last();
		BValue& refer = value.refer();
		bool result = true;
		if (refer.empty())
			result = false;
		else if (refer.is<bool>())
			result = value;
		else if (refer.is<char>())
			result = (char)value;
		else if (refer.is<short>())
			result = (short)value;
		else if (refer.is<int>())
			result = (int)value;
		else if (refer.is<long>())
			result = (long long)value;
		else if (refer.is<BReal>())
			result = (BReal)value;
		else if (refer.is<float>())
			result = (float)value;
		else if (refer.is<double>())
			result = (double)value;
		if (exp->name == '!')
			value = !result;
		else
			value = result;
		return current + 1;
	}
	case Syntax_And:
	{
		int top = stack.size() - 1;
		BValue& prev = stack[stack.size() - 2];
		BValue& next = stack[stack.size() - 1];
		bool prev_val = prev;
		bool next_val = next;
		prev = (prev_val && next_val);
		this->backStack(top);
		return current + 1;
	}
	case Syntax_Or:
	{
		int top = stack.size() - 1;
		BValue& prev = stack[stack.size() - 2];
		BValue& next = stack[stack.size() - 1];
		bool prev_val = prev;
		bool next_val = next;
		prev = (prev_val || next_val);
		this->backStack(top);
		return current + 1;
	}
	case Syntax_Equal:
	{
		int top = stack.size() - 1;
		BValue& prev = stack[stack.size() - 2];
		BValue& next = stack[stack.size() - 1];
		if (exp->name == "!=")
			prev = (prev.refer() != next.refer());
		else
			prev = (prev.refer() == next.refer());
		this->backStack(top);
		return current + 1;
	}
	case Syntax_If:
	{
		bool condition = stack.last();
		if (condition)
			return current + 1;
		int pos = exp->value;
		return pos;
	}
	case Syntax_Else:
	{
		return exp->value;
	}
	case Syntax_For:
	{
		bool condition = stack.last();
		if (condition)
		{
			stack.last() = exp;
			return current + 1;
		}
		int pos = exp->value;
		return pos;
	}
	case Syntax_While:
	{
		bool condition = stack.last();
		if (condition)
		{
			stack.last() = exp;
			return current + 1;
		}
		int pos = exp->value;
		return pos;
	}
	case Syntax_Continue:
	{
		int next = exp->value;
		for (int i = stack.size() - 1; i >= 0; i--)
		{
			if (BExp* exp = stack[i])
			{
				if (exp->syntax == Syntax_For || exp->syntax == Syntax_While)
				{
					this->backStack(i);
					return next;
				}
			}
		}
		errorMessage(exp) << "perform continue failed.";
		boss->post(Signal_Error, message);
		break;
	}
	case Syntax_Break:
	{
		int pos = exp->value;
		return pos;
	}
	case Syntax_Return:
	{
		for (int i = stack.size() - 1; i >= 0; i--)
		{
			if (CallInfo* cinfo = stack[i])
			{
				int back = cinfo->pos;
				if (cinfo->type.size())
				{
					BValue& res = stack[cinfo->top];
					typeMap[cinfo->top] = cinfo->type;
					nameMap[cinfo->top].reset();
					BValue& var = stack.last();
					if (cinfo->type.endWith('&') || cinfo->type.endWith('*'))
					{
						BValue& ref = var.refer();
						res = ref;
					}
					else
					{
						res = var.refer();
					}
					cinfo->top++;
				}
				this->backStack(cinfo->top);
				return back;
			}
		}
		int pos = exp->value;
		return pos;
	}
	case Syntax_Jump:
	{
		int next = exp->value;
		return next;
	}
	case Syntax_Enum:
		return current + 1;
	case Syntax_Key:
	{
		typeMap[stack.size()] = exp->type;
		stack.push(exp->value);
		return current + 1;
	}
	case Syntax_Begin:
	{
		for (int i = stack.size() - 1; i >= 0; i--)
		{
			BValue& var = stack[i];
			if (var.is<BExp>())
				break;
			if (nameMap(i).empty())
				this->backStack(i);
			else
				break;
		}
		stack.push(exp);
		return current + 1;
	}
	case Syntax_End:
	{
		if (exp->value.empty())
		{
			for (int i = stack.size() - 1; i >= 0; i--)
			{
				BExp* exp = stack[i];
				if (exp && exp->syntax == Syntax_Begin)
				{
					if (CallInfo* cinfo = stack(i - 1))
					{
						int back = cinfo->pos;
						if (cinfo->type.size())
							cinfo->top++;
						this->backStack(cinfo->top);
						return back;
					}
					this->backStack(i);
					break;
				}
			}
			return current + 1;
		}
		int line = exp->value;
		for (int i = stack.size() - 1; i >= 0; i--)
		{
			BValue& var = stack[i];
			if (var.is<CallInfo>())
				break;
			if (BExp* begin = var)
			{
				if (begin->value == line)
				{
					this->backStack(i);
					return current + 1;
				}
			}
		}
		errorMessage(exp) << "end failed : begin " << line << " lost.";
		boss->post(Signal_Error, message);
		return sequence.size();
	}
	case Syntax_Function:
	{
		CallInfo* cinfo = stack.last();
		BValue* argv = stack.data() + cinfo->top;
		return current + 1;
	}
	case Syntax_Method:
	{
		CallInfo* cinfo = stack.last();
		if (!cinfo)
		{
			errorMessage(exp) << "perform call method failed : " << exp->name << " call info is empty.";
			boss->post(Signal_Error, message);
			return current;
		}
		BValue* argv = stack.data() + cinfo->top;
		return current + 1;
	}
	default:
		errorMessage(exp) << "invalid syntax : " << exp->syntax;
		boss->post(Signal_Error, message);
		break;
	}
	error = true;
	return current;
}
void member_BScript::backStack(int pos)
{
	stack.back(pos);
	auto it = nameMap.find(pos);
	if (it.valid())
	{
		nameMap.remove(it.index(), nameMap.size());
		typeMap.remove(it.index(), typeMap.size());
	}
}
BValue* member_BScript::variant(const BString& name)
{
	for (int i = stack.size() - 1; i >= global; i--)
	{
		BValue& value = stack[i];
		if (nameMap(i) == name)
			return &value;
		if (CallInfo* cinfo = value)
		{
			while (--i >= cinfo->top)
			{
				BValue& value = stack[i];
				if (nameMap(i) == name)
					return &value;
			}
			break;
		}
	}
	for (int i = 0; i < global; i++)
	{
		BValue& var = stack[i];
		if (nameMap(i) == name)
			return &var;
	}
	for (int i = 0; i < presetVariants.size(); i++)
	{
		VariantInfo& var = presetVariants[i];
		if (var.name == name)
			return &var.value;
	}
	for (int i = 0; i < inclibs.size(); i++)
	{
		ILibrary* library = inclibs[i]->value;
		if (!library)
			continue;
		for (int i = 0; i < library->variants.size(); i++)
		{
			VariantInfo& var = library->variants[i];
			if (var.name == name)
				return &var.value;
		}
	}
	return 0;
}
BValue* member_BScript::findVariant(const BString& path)
{
	int pos = path.find('.');
	if (pos < path.size())
	{
		BString name;
		path.substr(name, 0, pos);
		BValue* ptr = this->variant(name);
		if (!ptr)
			return 0;
		while (pos < path.size())
		{
			pos = path.word(name, pos);
			if (name == '.')
				continue;
			BClass* obj = *ptr;
			if (!obj)
				return 0;
			int index = class_member(obj)->variants.find(name);
			if (index == class_member(obj)->variants.size())
				return 0;
			VariantInfo& vinfo = class_member(obj)->variants[index];
			ptr = &(vinfo.value);
		}
		return ptr;
	}
	return this->variant(path);
}
FuncInfo* member_BScript::findFunction(const BString& name)
{
	if (FuncInfo* finfo = presetFunctionMap(name))
		return finfo;
	if (FuncInfo* finfo = functionMap(name))
		return finfo;
	for (int i = 0; i < inclibs.size(); i++)
	{
		ILibrary* library = inclibs[i]->value;
		if (!library)
			continue;
		if (FuncInfo* finfo = library->functionMap(name))
			return finfo;
	}
	return 0;
}
BClass* member_BScript::createTempClass(const BString& name)
{
	int begin = name.find('<');
	if (begin < name.size())
	{
		int end = name.find('>');
		BString type;
		name.substr(type, 0, begin);
		BClass* cls = boss->findClass(type);
		if (!cls)
			return 0;
		int param_count = name.count(',') + 1;
		if (class_member(cls)->tempTypes.size() != param_count)
			return 0;
		BClass* tmpcls = boss->findClass(name);
		if (!tmpcls)
		{
			tmpcls = cls->clone();
			class_member(tmpcls)->instantiate(name);
			classMap[name] = tmpcls;
		}
		return tmpcls;
	}
	return 0;
}
bool member_BScript::locateVariant(BValue* vptr, BString& type, BString& name)
{
	type.reset();
	name.reset();
	int index = stack.index(vptr);
	if (stack.check(index))
	{
		type << typeMap(index);
		name << nameMap(index);
		return true;
	}
	for (int i = 0; i < presetVariants.size(); i++)
	{
		VariantInfo& vinfo = presetVariants[i];
		if (&vinfo.value == vptr)
		{
			type << vinfo.type;
			name << vinfo.name;
			return true;
		}
	}
	return false;
}
